var Dribbble = Dribbble || {};

Dribbble.Bucket = function(options) {
	this.options = options || {};
	this.type    = options.type || "bucket";
	this.target  = $(options.target);

	this.createDialog();
	this.bindEventListeners();
};

Dribbble.Bucket.prototype = {
	bindEventListeners: function() {
		this.target.live("click", $.proxy(this.show, this));

		this.dialog
			.click($.proxy(this.hideDialog, this))
			.keyup($.proxy(this.navigate, this))
			.delegate("a.close", "click", $.proxy(this.hide, this))
			.delegate(".add .close", "click", $.proxy(this.hide, this))
			.delegate(".create form .cancel", "click", $.proxy(this.hideCreate, this))
			.delegate(".create form", "submit", $.proxy(this.create, this))
			.delegate(".add a.create", "click", $.proxy(this.showCreate, this))
			.delegate("ol li a", "click", $.proxy(this.toggleClicked, this))
			.delegate("#bucket_query", "keyup", $.proxy(this.search, this))
			.delegate("#bucket_search", "submit", function() { return false; })
			.delegate("ol li", "mousemove", $.proxy(this.onMouseMove, this));
	},

	create: function(event) {
		var self  = this;
		var $form = $(event.target);

		$.ajax({
			"type" : "POST",
			"url"  : $form.attr("action"),
			"data" : $form.serialize(),
			"beforeSend" : function() {
				$("#bucket-add form input[type=submit]")
					.addClass("processing")
					.attr("disabled", "true")
					.attr("value", "Processing, please wait...");
			},
			"statusCode" : {
				201: function(data) {
					self.refresh(data);
				},
				200: function(data) {
					self.dialog.find(".create-bucket").html(data);
				}
			}
		}, "json");

		return false;
	},

	createDialog: function() {
		this.dialog = $("<div />", { "id" : this.type + "-overlay", "class" : "overlay" })
			.appendTo("body")
			.append(
				$("<div />", { "id" : this.type + "-add", "class" : "lightbox" })
					.append(
						$("<a />", { "href" : "#", "class" : "close" }).append(
							$("<img />", { "src" : "/images/icon-x-lg.png" })
						)
					)
					.append(
						$("<div />", { "class" : "display" })
							.append($("<div />", { "class" : "processing", "text" : "Loading..." }))
					)
			);
	},

	hasItems: function() {
		return this.dialog.find(".add ol li").length > 0;
	},

	hide: function() {
		$("body").css("overflow", "auto");

		if (this.type == "bucket") {
			$(".meta-act .bucket").load("/shots/" + this.options.screenshotId + "/buckets_menu");
		}

		this.dialog.fadeOut(function() {
			$(this).find(".display")
				.html($("<div />", { "class" : "processing", "text" : "Loading..." }));
		});

		return false;
	},

	hideCreate: function() {
		if (this.hasItems()) {
			this.showAdd();
		} else {
			this.hide();
		}
	},

	hideDialog: function(event) {
		if ($(event.target).attr("id") == this.dialog.attr("id")) {
			this.hide();
		}
	},

	navigate: function(event) {
		var query = $("#bucket_query");

		if (!query.is(":visible")) {
			return;
		}

		switch (event.which) {
			case 13: // Enter
				if (this.type == "project" && this.current && this.current.hasClass("bucketed")) {
					this.dialog.find("#bucket_form").submit();
				} else {
					this.toggle(this.current);
				}
			break;

			case 27: // Escape
				if ($.trim(query.val()) == "") {
					this.hide();
				} else {
					query.val("").trigger("keyup");
				}
			break;

			case 38: // Up
			case 40: // Down
				var element = (event.which == 38 ? this.current.prev() : this.current.next());

				this.select(element, { "scrollIntoView" : true });
			break;
		}

		return false;
	},

	onMouseMove: function(event) {
		if (this.scrolling) {
			return;
		}

		var element = $(event.target).closest("li");

		if (element.get(0) == this.current.get(0)) {
			return;
		}

		this.select(element);
	},

	refresh: function(options) {
		var self = this;

		options = options || {};

		this.dialog.find(".display").load(this.options.listUrl, function() {
			if (self.hasItems()) {
				self.showAdd();

				if (options.id) {
					var id = "#" + self.type + "-" + options.id;

					self.select(id);
					self.toggle(id);
				} else {
					self.select("ol.group li:first-child");
				}
			} else {
				self.showCreate();
			}

			self.dialog.find("ol.group").scroll(function() {
				clearTimeout(self.scrolling);

				self.scrolling = setTimeout(function() {
					self.scrolling = false;
				}, 250);
			});
		});
	},

	search: function(event) {
		// Ignore navigation keys.
		if (event) {
			switch (event.which) {
				case 13: // Enter
				case 27: // Escape
				case 38: // Up
				case 40: // Down
					event.preventDefault();

					return;
			}
		}

		var query = this.dialog.find("#bucket_query").val().toLowerCase();

		this.dialog.find("ol.group li")
			.each(function() {
				var element = $(this);
				var title   = element.find("a strong").text();

				if (title.toLowerCase().search(query) > -1) {
					element.show();
				} else {
					element.hide();
				}
			})
			.sort(function(a, b) {
				var aTitle    = $(a).find("a strong").text();
				var bTitle    = $(b).find("a strong").text();
				var aPosition = aTitle.toLowerCase().search(query);
				var bPosition = bTitle.toLowerCase().search(query);

				if (aPosition == bPosition) {
					return aTitle > bTitle ? 1 : -1;
				} else {
					return aPosition > bPosition ? 1 : -1;
				}
			})
			.appendTo(this.dialog.find("ol.group"));

		this.select(this.dialog.find("ol.group li:visible").eq(0));
	},

	select: function(selector, options) {
		var element = $(selector);

		if (element.length == 0) {
			return false;
		}

		if (this.current) {
			this.current.removeClass("current");
		}

		this.current = element;
		this.current.addClass("current");

		if (options && options.scrollIntoView) {
			element.get(0).scrollIntoView(false);
		}

		return false;
	},

	show: function() {
		// TODO: Get rid of the global.
		showOverlay(this.dialog);

		this.refresh();
		this.dialog.show();

		$("body").css("overflow", "hidden");

		return false;
	},

	showAdd: function() {
		this.dialog
			.find(".add").show().end()
			.find(".create-bucket").hide().end();

		$("#bucket_query").focus();
	},

	showCreate: function() {
		this.dialog
			.find(".add").hide().end()
			.find(".create-bucket").show().end();

		$("#bucket_name").focus();
	},

	toggle: function(selector) {
		var element = this.dialog.find(selector);

		if (this.type == "bucket") {
			var url      = $("#bucket_form").attr("action");
			var callback = $.proxy(function(html) {
				element.replaceWith(html)

				this.select("#bucket-" + element.modelId());
			}, this);

			if (element.hasClass("bucketed")) {
				$.ajax(url + "/" + element.modelId(), { "type" : "DELETE", "success" : callback });
			} else {
				$.post(url, { "bucket_id" : element.modelId(), "screenshot_id" : this.screenshotId }, callback);
			}

			element.toggleClass("bucketed");
		} else {
			element
				.addClass("bucketed")
				.siblings()
					.addClass("unbucketed")
					.removeClass("bucketed");

			this.dialog
				.find("form input[name=bucket_id]")
					.val(element.modelId())
				.end()
				.find(".add form button.form-sub")
					.attr("disabled", false)
				.end();
		}

		$("#bucket_query").focus();

		return false;
	},

	toggleClicked: function(event) {
		return this.toggle($(event.target).closest("li"));
	}
};
